#ifndef __BE_VM__
#define __BE_VM__

class Cmd
{
 private:
  UINT16 cmd;
  
 protected:
  void write(std::ostream &_os, const StringHash &_name) const;
  void write(std::ostream &_os, const float &_value) const;
  void write(std::ostream &_os, const UINT16 &_cmd) const;
  
 public:
  Cmd(const UINT16 &_cmd);
  virtual ~Cmd();
  void write(std::ostream &_os) const;
  virtual void internalWrite(std::ostream &_os) const = 0;
  virtual void printOut() const = 0;
};

class CreateObject : public Cmd
{
 private:
  StringHash name;
  StringHash model;

 public:
  CreateObject(const StringHash &_name, const StringHash &_model);
  ~CreateObject();
  void internalWrite(std::ostream &_os) const;
  void printOut() const;
};

class End : public Cmd
{
 public:
  End();
  ~End();
  void internalWrite(std::ostream &_os) const;
  void printOut() const;
};

class SetValue : public Cmd
{
 private:
  StringHash name;
  float      value;
  
 public:
  SetValue(const StringHash &_name, const float &_value);
  ~SetValue();

  void internalWrite(std::ostream &_os) const;
  void printOut() const;
};

class VM
{
 public:
  enum 
  {
    CMD_ERROR  = 0,
    CMD_CREATE,
    CMD_SETVALUE,
    CMD_END,
  };

 private:
  static VMPtr inst;
  std::ifstream ifs;

  VM();

  template<class _X>
    void read(std::istream &is, _X &ret)
    {
      _X tmp;

      if (is.eof())
	return;

      is.read((char*) &tmp, sizeof(_X));
      
      if (is.eof())
	return;

      ret = tmp;
    }

  bool doCreate(const StringHash &_param1, const StringHash &_param2);
  bool doSetValue(const StringHash &_param, const float &_value);
  bool doEnd();

 public:
  ~VM();

  static VMPtr instance();

  int open(const char *const _filename);
  int run();
};

class CmdList
{
 private:
  typedef std::list<CmdPtr> ListType;
  ListType cmdList;

 public:
  CmdList();
  ~CmdList();

  void addCreateObject( const String &_name, const String &_model );
  void addSetValue( const String &_name, const float &_value );
  void addEnd();

  void write(std::ostream &_os);
  void printOut();

};
#endif
